Skip to content

Proposed TreeList widget#987

Draft
jeremypw wants to merge 4 commits into
mainfrom
jeremypw/TreeList
Draft

Proposed TreeList widget#987
jeremypw wants to merge 4 commits into
mainfrom
jeremypw/TreeList

Conversation

@jeremypw

@jeremypw jeremypw commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
Screenshot from 2026-07-23 16 39 03

The old Granite.SourceList is still used in Code (twice) and Mail and a similar treelist widget could be useful elsewhere.

The proposed widget is the basis of the FolderManager and SymbolPane in the current port of Code to Gtk4 so the capabilities are directed towards that use.

A simple demo is provided to indicate the appearance (but not the behaviour at the moment)

It is appreciated that the commenting and layout does not meet Granite standards but this is pushed for initial comment.

The widget items provide a primary icon, text (with tooltip), secondary icon (with tooltip) and badge. Those marked "is_expandable" get an expander. Dummy items on empty folders are not yet implemented (the expander is shown for empty folders).

As well as the native Gtk abilities, the rows signal when a context menu is requested.

@jeremypw
jeremypw requested a review from a team July 23, 2026 15:35
@danirabbit

Copy link
Copy Markdown
Member

FWIW I think ultimately Mail will probably not need a tree view. It needs at most one level below section headers and usually not even that. We could probably just flatten folders in Mail and nobody would notice or care

So it might be the Code is the only app whose sidebar needs a tree?

@jeremypw

jeremypw commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

@danirabbit Oh, OK. I hadn't gotten round to looking closely at Mail.

Photos also uses a multilevel expandable tree for a sidebar.

I note that Google Mail e.g. uses a tree in the sidebar for labels which might be a future feature of Mail (see issue #339)

I did think that Files might use this for a new view - a kind of vertical equivalent of ColumnView in combination with the new preview widget.

Another advantage is that perfecting the widget seperately here means a smaller diff for the Code port.

@jeremypw
jeremypw marked this pull request as draft July 24, 2026 08:52
@jeremypw

jeremypw commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Converting to draft. I'll continue to work on this here - it can easily be moved back to the Gtk4 port of Code later if required.

@leolost2605

Copy link
Copy Markdown
Member

IMO we shouldn't wrap the Gtk.TreeListModel by using custom items. I think we should focus on listmodels and use them in the apps data model already (e.g. a Folder class just provides a listmodel of children and not a gee list or similar). Then putting that in a treelistmodel is super easy and everything will be less code than having to manually bind your dynamic data to custom items.

In my experience it leads to a better structure in the app, better separation between UI and Data and is easier to use with less code and less things that can go wrong.

IMO it would also be easier and more flexibel to implement this by just providing the widgets that make up the actual rows (like Granite.ListItem) instead of providing a whole list widget. The boiler plate for apps won't be that big (creating a listview and having a minimal factory that just creates our provided widget and binds the properties of the data item to the widget).
For example we could add a method to granite.listitem along the lines of bind_tree_row, a style enum like compact or rich where compact would make the rows more compact for use in a sidebar or similar and the option to add an icon.

But a whole list widget that wraps the list view and sets up the factory could work too ig.

@jeremypw

jeremypw commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

@leolost Thanks for your input. I am a bit confused - the Gtk.TreeListModel is intended to wrap a Gtk.ListModel and provides the mechanism for expanding rows and loading children. I think what you are saying is to not include a specific widget factory in TreeList but let each app create their own. You are probably right for a library widget - this is a symptom of this early push originally being specific for Code. We could make the widget unsealed, virtualise the factory functions as well as making the base item interface simpler. The widget does provide useful functions like iterate_children and the popup_context_menu signal and potentially more.

I agree that we would need to provide a mechanism for styling the rows according to the data. That will be needed in Code as well as some rows are "dim" and others not.

@leolost2605

leolost2605 commented Jul 24, 2026

Copy link
Copy Markdown
Member

@leolost Thanks for your input. I am a bit confused - the Gtk.TreeListModel is intended to wrap a Gtk.ListModel and provides the mechanism for expanding rows and loading children. I think what you are saying is to not include a specific widget factory in TreeList but let each app create their own. You are probably right for a library widget - this is a symptom of this early push originally being specific for Code. We could make the widget unsealed, virtualise the factory functions as well as making the base item interface simpler. The widget does provide useful functions like iterate_children and the popup_context_menu signal and potentially more.

@jeremypw sorry for the confusion. With wrapping I meant something different, I meant that with the current api in this PR the gtk.treelistmodel is kept private and can only be indirectly accessed by calling things like add_root_item and add_child. However I think the calling code (the app) should provide the tree model directly because that will be so much easier for them if done right.

For example say you want to show a folder structure.

With the current implementation you have your folder class with a list (any list type) of children folders. Then initially you need to iterate the list and call add_child for every child. Then you need signals child_added and child_removed, manually subscribe to them and call add_child and remove_child on the TreeListItem. Furthermore for every child you add, you have to make sure that its signals are in turn set up for the next level.

Instead if you immediately go with GLib.ListModel you have a class Folder that contains a listmodel children. Then instead of having to manually listen to signals and calling into the TreeList(Items) while managing all the references you just do
new Gtk.TreeListModel(root_folder.children, ..., (obj) => ((Folder) obj).children); and you're done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants